home *** CD-ROM | disk | FTP | other *** search
/ Amiga Game-Power / Amiga Game-Power.iso / pd mix ii / access / hddriver / driver / trackcache.c < prev    next >
C/C++ Source or Header  |  1994-05-20  |  4KB  |  209 lines

  1.  
  2. /*
  3.  * Copyright 1987 Alan Kent
  4.  *
  5.  * Permission is granted to redistribute this code as long
  6.  * as this message is retained in the code and the code is
  7.  * not sold without written permission from the author.
  8.  *
  9.  * UUCP: {seismo,hplabs,mcvax,ukc,nttlab}!munnari!goanna.oz!ajk
  10.  * ACSnet: ajk@goanna.oz
  11.  * ARPA: munnari!goanna.oz!ajk@SEISMO.ARPA
  12.  */
  13.  
  14.  
  15. #include "hd.h"
  16.  
  17.  
  18. extern struct Node *RemTail ();
  19.  
  20.  
  21. #define CACHE_SIZE        10
  22.  
  23.  
  24. static struct cache {
  25.  
  26.     struct Node node;
  27.     struct posn posn;
  28.     UBYTE *        buf;
  29.  
  30. } cache[ CACHE_SIZE ];
  31.  
  32.  
  33. static struct List history;
  34.  
  35.  
  36. void
  37. clear_all ()
  38. {
  39.     register int i;
  40.     register struct cache *c;
  41.  
  42.     NewList ( &history );
  43.     for ( i = 0; i < CACHE_SIZE; i++ ) {
  44.         c = &cache[i];
  45.         c->posn.cylinder = -1;
  46.         c->node.ln_Pri = 0;
  47.         AddTail ( &history , c );
  48.     }
  49. }
  50.  
  51.  
  52. void
  53. flush_all ()
  54. {
  55. }
  56.  
  57.  
  58. int
  59. init_cache ()
  60. {
  61.     int i;
  62.  
  63.     for ( i = 0; i < CACHE_SIZE; i++ ) {
  64.         if ( ( cache[i].buf = (UBYTE *) AllocMem (
  65.         (LONG)HD_SECTOR * first.sectors , (LONG)MEMF_CLEAR ) ) == NULL ) {
  66.             while ( --i >= 0 )
  67.                 FreeMem ( cache[i].buf , (LONG)HD_SECTOR * first.sectors );
  68.             return ( -1 );
  69.         }
  70.     }
  71.     clear_all ();
  72.     return ( 0 );
  73. }
  74.  
  75.  
  76. void
  77. free_cache ()
  78. {
  79.     register int i;
  80.  
  81.     for ( i = 0; i < CACHE_SIZE; i++ )
  82.         FreeMem ( cache[i].buf , (LONG)HD_SECTOR * first.sectors );
  83. }
  84.  
  85.  
  86. UBYTE *
  87. read_cache ( posn )
  88. struct posn *posn;
  89. {
  90.     register struct cache *c;
  91.     int status;
  92.     static UBYTE single_buf[ HD_SECTOR ];
  93.  
  94.  
  95.     /* see if track is in the cache */
  96.  
  97.     for ( c = (struct cache *) history.lh_Head;
  98.     c->node.ln_Succ != NULL;
  99.     c = (struct cache *) c->node.ln_Succ ) {
  100.  
  101.         if ( posn->cylinder == c->posn.cylinder
  102.         &&   posn->surface == c->posn.surface ) {
  103.  
  104.             /* recalculate priority so is not pushed out of list */
  105.  
  106.             Remove ( c );
  107.             calc_priority ( c );
  108.             Enqueue ( &history , c );
  109.             return ( &c->buf[ posn->sector * (LONG)HD_SECTOR ] );
  110.         }
  111.     }
  112.  
  113.     /* ok, decrease cache weights so new tracks have better chance */
  114.  
  115.     for ( c = (struct cache *) history.lh_Head;
  116.     c->node.ln_Succ != NULL;
  117.     c = (struct cache *) c->node.ln_Succ ) {
  118.         if ( c->node.ln_Pri > 0 )
  119.             c->node.ln_Pri--;
  120.     }
  121.  
  122.     /* not in cache */
  123.  
  124.     c = (struct cache *) RemTail ( &history );
  125.     c->posn = *posn;
  126.     status = read_track ( &c->posn , c->buf );
  127.     if ( status != 0 ) {
  128.         AddTail ( &history , c );
  129.         c->posn.cylinder = -1;
  130.         status = read_sector ( &c->posn , &single_buf[0] );
  131.         if ( status != 0 )
  132.             status = read_sector ( &c->posn , &single_buf[0] );
  133.             if ( status != 0 )
  134.                 status = read_sector ( &c->posn , &single_buf[0] );
  135.                 if ( status != 0 )
  136.                     return ( NULL );
  137.         return ( &single_buf[0] );
  138.     }
  139.     calc_priority ( c );
  140.     Enqueue ( &history , c );
  141.     return ( &c->buf[ posn->sector * (LONG)HD_SECTOR ] );
  142. }
  143.  
  144.  
  145. void
  146. write_cache ( posn , buf )
  147. register struct posn *posn;
  148. UBYTE *buf;
  149. {
  150.     register struct cache *c;
  151.  
  152.  
  153.     /* if in cache, make sure updated in cache */
  154.  
  155.     for ( c = (struct cache *) history.lh_Head;
  156.     c->node.ln_Succ != NULL;
  157.     c = (struct cache *) c->node.ln_Succ ) {
  158.  
  159.         if ( posn->cylinder == c->posn.cylinder
  160.         &&   posn->surface == c->posn.surface ) {
  161.  
  162.             /* update cache */
  163.  
  164.             copy_sector ( buf , &c->buf[ posn->sector * (LONG)HD_SECTOR ] );
  165.             break;
  166.         }
  167.     }
  168.  
  169.     write_sector ( posn , buf );
  170. }
  171.  
  172.  
  173. static
  174. calc_priority ( c )
  175. struct cache *c;
  176. {
  177.     register UBYTE *p;
  178.     register LONG type , subtype;
  179.     register int sector;
  180.     register int priority;
  181.  
  182.  
  183.     /* ok, now lets peek inside the sectors to see if this track */
  184.     /* contains anything juicy. Directory entries get extra points */
  185.     /* because of the way they are scattered all over the place. */
  186.     /* Data blocks get less because they are only likely to be used */
  187.     /* once. */
  188.  
  189.     priority = 0;
  190.  
  191.     for ( sector = 0, p = c->buf;
  192.     sector < first.sectors;
  193.     sector++, p += HD_SECTOR ) {
  194.  
  195.         type = ((LONG*)p) [ 0 ];
  196.         subtype = ((LONG*)p) [ 127 ];
  197.  
  198.         if ( type == 2  &&  subtype == 2        /* File Header */
  199.         ||   type == 2  &&  subtype == -3        /* User Directory */
  200.         ||   type == 16 &&  subtype == -3 )        /* file extension */
  201.             priority += 2;
  202.  
  203.         if ( type == 8 )                        /* data block */
  204.             priority += 1;
  205.     }
  206.  
  207.     c->node.ln_Pri = priority;
  208. }
  209.